package airthmetic.exercise.search;

import java.util.*;

/**
 * 字典 wordList 中从单词 beginWord 和 endWord 的 转换序列 是一个按下述规格形成的序列 beginWord -> s1 -> s2 -> ... -> sk：
 *
 * 每一对相邻的单词只差一个字母。
 *  对于 1 <= i <= k 时，每个 si 都在 wordList 中。注意， beginWord 不需要在 wordList 中。
 * sk == endWord
 * 给你两个单词 beginWord 和 endWord 和一个字典 wordList ，返回 从 beginWord 到 endWord 的 最短转换序列 中的 单词数目 。如果不存在这样的转换序列，返回 0 。
 *
 *
 * 示例 1：
 *
 * 输入：beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log","cog"]
 * 输出：5
 * 解释：一个最短转换序列是 "hit" -> "hot" -> "dot" -> "dog" -> "cog", 返回它的长度 5。
 * 示例 2：
 *
 * 输入：beginWord = "hit", endWord = "cog", wordList = ["hot","dot","dog","lot","log"]
 * 输出：0
 * 解释：endWord "cog" 不在字典中，所以无法进行转换。
 *
 *
 * 提示：
 *
 * 1 <= beginWord.length <= 10
 * endWord.length == beginWord.length
 * 1 <= wordList.length <= 5000
 * wordList[i].length == beginWord.length
 * beginWord、endWord 和 wordList[i] 由小写英文字母组成
 * beginWord != endWord
 * wordList 中的所有字符串 互不相同
 */


public class _127_单词接龙2 {
    // 单向方式
    public int ladderLength(String beginWord, String endWord, List<String> wordList) {
        Set<String> set = new HashSet<>(wordList);
        if(!set.contains(endWord)){
            return 0;
        }

        Queue<String> queue = new LinkedList<>();
        Set<String> visited = new HashSet<>();
        queue.offer(beginWord);
        visited.add(beginWord);
        int step = 1;
        while(!queue.isEmpty()){
            int size = queue.size();
            for (int i=0; i<size; i++){
                String str = queue.poll();


                boolean b = canConvert(str, endWord, set, visited, queue);
                if(b){
                    return step + 1;
                }
            }
            step++;
        }
        return 0;
    }

    private boolean canConvert(String word, String endWord, Set<String> set, Set<String> visited, Queue<String> queue ) {
        char[] charArray = word.toCharArray();
        for (int i=0; i<charArray.length; i++){
            char orngin = charArray[i];
            for(char c ='a'; c<='z'; c++){
                if (c == orngin){
                    continue;
                }
                charArray[i] = c;
                String newWord = new String(charArray);
                if(endWord.equals(newWord)){
                    return true;
                }

                if (newWord.equals(endWord) && !visited.contains(newWord)){
                    queue.offer(new String(charArray));
                    visited.add(new String(charArray));
                }
            }
            charArray[i] = orngin;
        }
        return false;

    }


}
